package cn.szabadsag.hrm.service.impl;

import cn.szabadsag.hrm.context.LoginContext;
import cn.szabadsag.hrm.domain.KillOrder;
import cn.szabadsag.hrm.domain.KillOrderItem;
import cn.szabadsag.hrm.domain.LoginUser;
import cn.szabadsag.hrm.dto.KillOrderDto;
import cn.szabadsag.hrm.dto.OrderSaveDto;
import cn.szabadsag.hrm.exception.Assert;
import cn.szabadsag.hrm.mapper.KillOrderMapper;
import cn.szabadsag.hrm.service.IKillOrderItemService;
import cn.szabadsag.hrm.service.IKillOrderService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author yangcong
 * @since 2022-04-22
 */
@Service
@Slf4j
public class KillOrderServiceImpl extends ServiceImpl<KillOrderMapper, KillOrder> implements IKillOrderService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private IKillOrderItemService itemService;

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 保存订单
     * @param dto:参数
     * @return  返回订单号
     */
    @Override
    @Transactional
    public String saveOrder(OrderSaveDto dto) {
        //  1.参数判断
        //  2.条件判断：必须登录
        /*
          测试数据
         */
        LoginUser login = new LoginUser();
        login.setId(3L);
        /*
        真实登录用户
         */
//        LoginUser login = LoginContext.getLogin();
        Assert.assertNotNull(login,"请登录！！！");
        //  3.根据订单号获取预创订单 - 从Redis中拿
        //  3.1.key:使用用户ID和订单号拼接，获取预创订单
        String key = "killorder:" + dto.getOrderNo() + ":" + login.getId();

        //  加锁  porder:表示预创订单
        RLock lock = redissonClient.getLock("porder" + dto.getOrderNo());
        lock.lock();
        log.info("下单逻辑，加锁.........");
        try {
            //  4.拿到预创订单
            KillOrderDto orderDto = (KillOrderDto) redisTemplate.opsForValue().get(key);
            Assert.assertNotNull(orderDto,"秒杀记录不存在或超时！！");
            //  4.1.构建业务订单数据(订单-明细)
            KillOrder killOrder = new KillOrder();
            killOrder.setCreateTime(new Date());//  创建时间
            killOrder.setKillCount(1);//秒杀数量
            killOrder.setOrderNo(dto.getOrderNo());//订单编号
            killOrder.setTotalPrice(orderDto.getPrice());//订单总价格
            killOrder.setStatusOrder(KillOrder.ORDER_STATUS_UNPAY);//订单状态 待支付
            killOrder.setUserId(login.getId());
            insert(killOrder);
            //  4.2保存到数据库
            KillOrderItem item = new KillOrderItem();
            item.setCreateTime(killOrder.getCreateTime());
            item.setCount(1);
            item.setCourseId(orderDto.getCourseId());
            item.setCourseName(orderDto.getCourseName());
            item.setCoursePic(orderDto.getCoursePic());
            item.setKillId(orderDto.getKillId());
            item.setKillOrderId(killOrder.getId());
            item.setPrice(orderDto.getPrice());
            itemService.insert(item);

            //  5.保存支付单
            //  5.1.构建支付单数据
            //  5.2.保存到支付数据库 - OpenFeign
            //  下单之后，删除预创单
            redisTemplate.delete(key);
        }finally {
            //  释放锁
            if (lock.isLocked())lock.unlock();
            log.info("下单逻辑，释放锁.........");
        }
        return dto.getOrderNo();
    }
}
